#include "sensors_data.h"
#include "pwm_trigger_depthData.h"
#include "usbConnect.h"
#include "dissolved_oxygen_sensor.h"
#include "PH.h"

#include <sys/syscall.h>
// #include <time.h>
#include <sys/time.h>
#include <pthread.h>

#include <sys/types.h>
#include <sys/stat.h>

#include <ctype.h>

#define PUMPDATADIRPATH "/home/pi/SamplePumpingData"

////测深数据文件序号
extern g_fileList g_pumpFileList;

//串口句柄
extern int g_serial_port_id[SERIAL_PORT_NUM];
extern int g_bef_serial_port_id[SERIAL_PORT_NUM];

//已经打开的串口名称
extern char g_sensors_open_serial[SERIAL_PORT_NUM][SERIAL_PORT_NAME_LEN];
extern char g_bef_sensors_open_serial[SERIAL_PORT_NUM][SERIAL_PORT_NAME_LEN];

//开启读取串口数据的线程id
pthread_t g_read_thread_id[SERIAL_PORT_NUM] = {0};
pthread_t g_bef_read_thread_id[SERIAL_PORT_NUM] = {0};

//test
int i_Check_Port = 0;

//接收到的GPS数据切割后的数据
char g_gps_split_data[15][100] = {0};
//接收到的测深数据
char g_sounder_recv_data[100] = {0};

char g_split_usb_sounding_data[50][512] = {0};
char g_split_usb_gps_data[50][512] = {0};

pthread_mutex_t sounding_data_mutex;
pthread_mutex_t gps_data_mutex;

struct senors_data_struct //gps经纬度，高度
{
    char soundingData[20];
    char latitude[20];
    char latitude_N_or_S[2];
    char longitude[20];
    char longitude_E_or_W[2];
    float water_temp; //水温
    float water_DOS; //溶解氧
    float water_PH; //PH值
    char altitude[10];//海拔高度

};

static float g_water_temp = 0; //水温传感器数据
static float g_DOS_temp = 0; //溶解氧传感器数据
static float g_PH_temp = 0; //PH传感器数据

struct senors_data_struct send_data_struct;

pthread_mutex_t sounding_data_mutex;
pthread_mutex_t gps_data_mutex;

void gpsCompanyChange(char *gps_EW, int len)
{
    if (gps_EW == NULL)
        return;
    double gps_E = 0;
    double gps_Ef = 0;
    // char *aaaaa = "11802.6426285";
    gps_E = atof(gps_EW);
    int gps_Ed = gps_E / 100;
    gps_Ef = gps_E - gps_Ed * 100;
    gps_Ef /= 60.0;

    gps_E = gps_Ed + gps_Ef;
    memset(gps_EW, 0, len);
    sprintf(gps_EW, "%.7f", gps_E);
    printf("aaaaaaaaaaaaaaaaaaaaaaaaaaaa%s\n", gps_EW);
}

/*******************************************************************
** 函数名:     splitGpsData
** 函数描述:   根据 "," 分割接收到的GPS数据
** 参数:      cData 需要用“，”进行分割的数据
********************************************************************/
void splitGpsData(char *cData)
{
    printf("aaaaaaaaaaaaaaaaaaaadddddddddddddddd%s\n", cData);
    char *ptr = NULL;
    int iIndex = 0;
    // memset(g_gps_split_data, 0, sizeof(g_gps_split_data));
    //  char aaaaaaaaaaaaaaaaa[100] = "$GPGGA,121252.000,2434.825,N,11804.996,E,1,05,2.0,45.9,M,-5.7,M,,0000*77";
    ptr = strtok(cData, ",");
    while (ptr != NULL)
    {
        pthread_mutex_lock(&gps_data_mutex);
        memcpy(g_gps_split_data[iIndex], ptr, strlen(ptr));
       // if (iIndex == 9)
         //   printf("高程==%d\n", g_gps_split_data[iIndex]);
        if (iIndex == 2 || iIndex == 4)
        {
            gpsCompanyChange(g_gps_split_data[iIndex], 100);
         //   printf("aaaaaaaaaaaaaaaaaaaadddddddddddddddd%s", g_gps_split_data[iIndex]);
        }

        pthread_mutex_unlock(&gps_data_mutex);
        ptr = strtok(NULL, ",");
        iIndex++;
    }
}

/*******************************************************************
** 函数名:     handleRecvData
** 函数描述:   处理usb口获取到的数据
** 返回:       recvBuff 获取的数据 recvLen获取的长度 type获取的数据类型 1为测深数据 2为gps数据
********************************************************************/
void handleRecvData(char *recvBuff, int recvLen, int type)
{
   // printf("2 GpsData= %s  len===\r\n", recvBuff, recvLen);
    char recvData[512] = {0};
    memset(recvData, 0, sizeof(recvData));
    // printf("data::%s\r\n", recvData);
    if (type == 2)
    {
        char *gpsData = strstr(recvBuff, "$GPGGA");
        if (gpsData != NULL)
        {
            char *endData = strstr(gpsData, "\r\n");
            // printf("------------------gps---------------------------------\n\n");
            // printf("%s",recvBuff);
            // printf("-------------------gps--------------------------------\n\n");
            // printf("1 endData-gpsData = %p -%p = %d\r\n",endData,gpsData,endData-gpsData);
            if (endData != NULL)
            {
                memcpy(recvData, gpsData, endData - gpsData);
                printf("2 splitGpsData= %s\r\n", recvData);
                splitGpsData(recvData);
            }
        }
    }
    else if (type == 1)
    {
        char *soundingData = strstr(recvBuff, "DA");
        if (soundingData != NULL)
        {
            // printf("------------------DA---------------------------------\n\n");
            // printf("%s",recvBuff);
            // printf("-------------------DA--------------------------------\n\n");
            char *extraData = strchr(soundingData, '*');
            // printf("2 soundingData= %s\r\n",soundingData);
            // printf("2 extraData= %s\r\n",extraData);
            memcpy(g_sounder_recv_data, soundingData + 2 * sizeof(char), extraData - soundingData - 2); //减去不需要的长度
            // printf("2 g_sounder_recv_data= %s\r\n",g_sounder_recv_data);
        }
    }
}

// void handleRecvData(char *recvBuff, int recvLen)
// {
//     char *soundingData = strstr(recvBuff, "DA");
//     char *gpsData = strstr(recvBuff, "$GPGGA");
//     if (soundingData != NULL)
//     {
//         char *testData = strchr(soundingData, 'm');
//         if (testData == NULL)
//         {
//             printf("错误数据！！！");
//             return;
//         }
//         int bTrueData = isdigit(recvBuff[2]);
//         char *extraData = strchr(soundingData, '*');
//         int len = strlen(soundingData) - strlen(extraData);
//         char compData[20] = {0};
//         if (len <= sizeof(compData))
//         {
//             memcpy(compData, soundingData, len);
//             // for (int i = 0; i < len; i++)
//             // {
//             //     printf("%c\r\n", compData[i]);
//             // }

//             handleCompData(compData, len);
//         }
//     }
//     else if (gpsData != NULL)
//     {
//         char *extraData = strchr(gpsData, '\n');
//         if (extraData == NULL)
//         {
//             return;
//         }
//         int len = strlen(gpsData) - strlen(extraData);
//         char compData[200] = {0};
//         printf("gps data !!!!");
//         if (len <= sizeof(compData))
//         {
//             memcpy(compData, gpsData, len);
//             // for (int i = 0; i < len; i++)
//             // {
//             //     printf("%c\r\n", compData[i]);
//             // }

//             handleCompData(compData, len);
//         }
//     }
// }

/*******************************************************************
** 函数名:     judgeSerialOpenAsBefore
** 函数描述:   判断串口打开状态是否与上一次相同
** 返回:       1 串口打开状态与上一次相同， 0 串口打开状态与上一次不相同
********************************************************************/
int judgeSerialOpenAsBefore()
{
    int i = 0;
    for (i = 0; i < SERIAL_PORT_NUM; i++)
    {
        if (strcmp(g_sensors_open_serial[i], g_bef_sensors_open_serial[i]) != 0)
        {
            // printf("value:%s, before: %s\r\n", g_sensors_open_serial[i], g_bef_sensors_open_serial[i]);
            return 0;
        }
    }
    return 1;
}

/*******************************************************************
** 函数名:     usbCheckReadThread
** 函数描述:   串口热插拔后开启或关闭串口和线程
********************************************************************/
void usbCheckReadThread(handleRecvDataCallBack handleCB)
{
    int i = 0;
    while (1)
    {
        openSensorsPort();
        int iSerialOpenAsBef = judgeSerialOpenAsBefore();
        if (iSerialOpenAsBef)
        {
            sleep(5); //给系统反应时间，太快系统资源未回收干净
            continue;
        }
        else
        {
            readFuncStruct funcStruc[SERIAL_PORT_NUM] = {0};
            for (i = 0; i < SERIAL_PORT_NUM; i++)
            {
                printf("usbCheckReadThread:   :i=%d %s, %d\r\n", i, g_sensors_open_serial[i], g_serial_port_id[i]);
                printf("usbCheckReadThread:bef:i=%d %s, %d\r\n", i, g_bef_sensors_open_serial[i], g_bef_serial_port_id[i]);
                if (strcmp(g_sensors_open_serial[i], g_bef_sensors_open_serial[i]) != 0)
                {
                    if (g_bef_serial_port_id[i] != 0 && (strcmp(g_sensors_open_serial[i], "") == 0))
                    {
                        void *threadRet = NULL;
                        pthread_cancel(g_read_thread_id[i]); //退出线程
                        int ret = pthread_join(g_read_thread_id[i], &threadRet);
                        closeSensorsPort(g_bef_serial_port_id[i]);
                        printf("kill Thread::[i=%d]关闭该口 ret=%d, threadRet=%d port:%d,befname=%s\r\n", i, ret, (int)threadRet, g_bef_serial_port_id[i], g_bef_sensors_open_serial[i]);
                        g_bef_serial_port_id[i] = 0;
                        g_serial_port_id[i] = 0;
                    }
                    if (strcmp(g_sensors_open_serial[i], "") != 0)
                    {
                        printf("create thread read:%s, i=%d,port=%d\r\n", g_sensors_open_serial[i], i, g_serial_port_id[i]);
                        funcStruc[i].portId = g_serial_port_id[i];
                        funcStruc[i].handleCB = handleRecvData;
                        if ((pthread_create(&g_read_thread_id[i], NULL, readSensorsPortCallBack, &funcStruc[i])) == -1)
                        {
                            printf("create error!\n");
                        }
                    }
                    g_bef_serial_port_id[i] = g_serial_port_id[i];
                }
            }
            memcpy(g_bef_sensors_open_serial, g_sensors_open_serial, sizeof(g_sensors_open_serial));
        }
        sleep(5); //给系统反应时间，太快系统资源未回收干净
    }
}

/*******************************************************************
** 函数名:     updateSendSensorsDataThread
** 函数描述:   向uart1口循环发送数据
** 参数:      sendSensorsDataToUart1 发送数据的回调函数
********************************************************************/
void updateSensorsDataCallBack(void (*sendSensorsDataToUart)(char *, int, char))
{
    char send_data[500] = {0};
    while (1)
    {
#define DOS //关闭RTK和测深检测
#ifndef DOS
        pthread_mutex_lock(&sounding_data_mutex);
        int iSounder = strcmp(g_sounder_recv_data, "") == 0;
        pthread_mutex_unlock(&sounding_data_mutex);
        int iGps = strcmp(g_gps_split_data[0], "") == 0;
        if (iSounder && iGps)
        {
            usleep(500000); //发送间隔时间500ms
            continue;
        }
        else
#endif
        {
            pthread_mutex_lock(&sounding_data_mutex);
            memcpy(send_data_struct.soundingData, g_sounder_recv_data, strlen(g_sounder_recv_data));
            pthread_mutex_unlock(&sounding_data_mutex);
            // char *aaaa = "123";
            // char *bbbb = "456";
            pthread_mutex_lock(&gps_data_mutex);
            memcpy(send_data_struct.latitude, g_gps_split_data[2], strlen(g_gps_split_data[2]));
            // memcpy(send_data_struct.latitude, aaaa, strlen(aaaa));
            printf("\n纬度==%s\n", send_data_struct.latitude);
            memcpy(send_data_struct.latitude_N_or_S, g_gps_split_data[3], strlen(g_gps_split_data[3]));
            memcpy(send_data_struct.longitude, g_gps_split_data[4], strlen(g_gps_split_data[4]));
            // memcpy(send_data_struct.longitude, bbbb, strlen(bbbb));
            printf("\n经度==%s\n", send_data_struct.longitude);
            memcpy(send_data_struct.longitude_E_or_W, g_gps_split_data[5], strlen(g_gps_split_data[5]));
            send_data_struct.water_temp = g_water_temp;
            send_data_struct.water_DOS = g_DOS_temp;
            send_data_struct.water_PH = g_PH_temp;
                memcpy(send_data_struct.altitude, g_gps_split_data[9], strlen(g_gps_split_data[9])); //海拔高度
            printf("高程==%s\n", send_data_struct.altitude);
            // for (int i = 0; i < 16; i++)
            // {

            //     printf("%s\n", g_gps_split_data[i]);
            // }
            pthread_mutex_unlock(&gps_data_mutex);

            // printf("%p, %s,%s,%s,%s\r\n", send_data, g_gps_split_data[2],g_gps_split_data[3],g_gps_split_data[4],g_gps_split_data[5]);
            memset(send_data, 0, sizeof(send_data));
            memcpy(send_data, &send_data_struct, sizeof(send_data_struct));
            // 0xb639ec5c, 000.59 m,123,N,456,E,68, 500

            printf("数据===%p, %s,%s,%s,%s,%s,%d, %d \r\n", send_data, send_data_struct.soundingData, send_data_struct.latitude, send_data_struct.latitude_N_or_S, send_data_struct.longitude, send_data_struct.longitude_E_or_W, sizeof(send_data_struct), sizeof(send_data));
            sendSensorsDataToUart(send_data, sizeof(send_data_struct), '0');
        }
        usleep(500000); //发送间隔时间500ms
    }
}

/*******************************************************************
** 函数名:     judgeDirIsExitOrMkdir
** 函数描述:   判断文件夹是否存在不存在则创建
** 参数：      dirPath 需要创建的文件夹路径
********************************************************************/
int judgeDirIsExitOrMkdir(char *dirPath)
{
    if (access(dirPath, 0) == -1)
    {
        printf("dir is not exist!!!!!\r\n");
        int flag = mkdir(dirPath, 0777);
        if (flag == 0)
        {
            printf("mkdir ok\n");
            return 1;
        }
        else
        {
            printf("mkdir fail\n");
            return 0;
        }
    }
    return 1;
}

/*******************************************************************
** 函数名:     pumpSaveGpsTimeToFile
** 函数描述:   采样抽水时记录3次gps数据, 每个桶开始抽水时记录一次
每行数据内容为时间+GPS数据
********************************************************************/
void pumpSaveGpsTimeToFile()
{
    time_t curTime;
    struct tm *timeNow;
    time(&curTime);
    timeNow = localtime(&curTime);
    char fullTime[100] = {0};
    char fileName[100] = {0};
    char fullFilePath[100] = {0};

    if (g_pumpFileList.FileNum < MAX_FILE_NUM)
    {
        g_pumpFileList.FileNum++;
        sprintf(fileName, "%d_%d.%d.%d_%d.%d.%d", g_pumpFileList.FileNum, timeNow->tm_year + 1900, timeNow->tm_mon + 1, timeNow->tm_mday, timeNow->tm_hour, timeNow->tm_min, timeNow->tm_sec);
    }
    else
    {
        g_pumpFileList.FileNum = 1;
        sprintf(fileName, "%d_%d.%d.%d_%d.%d.%d", g_pumpFileList.FileNum, timeNow->tm_year + 1900, timeNow->tm_mon + 1, timeNow->tm_mday, timeNow->tm_hour, timeNow->tm_min, timeNow->tm_sec);
    }
    sprintf(fullTime, "%d.%d.%d_%d:%d:%d", timeNow->tm_year + 1900, timeNow->tm_mon + 1, timeNow->tm_mday, timeNow->tm_hour, timeNow->tm_min, timeNow->tm_sec);
    // sprintf(fileName, "%d_%d_%d", timeNow->tm_hour, timeNow->tm_min, timeNow->tm_sec);

    printf(fileName);

    if (!judgeDirIsExitOrMkdir(PUMPDATADIRPATH))
    {
        printf("fail to mk PUMPDATADIRPATH!\n");
        return;
    }

    if (fileName == NULL)
    {
        printf("fileName is null\r\n");
        return;
    }

    sprintf(fullFilePath, "%s/%s.txt", PUMPDATADIRPATH, fileName);
    //  printf(fullFilePath);

    file_Contrast(PUMPDATADIRPATH, g_pumpFileList.FileNum);
    FILE *file = fopen(fullFilePath, "w");

    if (file == NULL)
    {
        printf("fail to open file!");
        return;
    }

    //test
    // memcpy(g_gps_split_data[2], "123456.1232", 12);
    // memcpy(g_gps_split_data[3], "N", 2);
    // memcpy(g_gps_split_data[4], "123456.1232", 12);
    // memcpy(g_gps_split_data[5], "N", 2);
    //

    pthread_mutex_lock(&gps_data_mutex);
    fprintf(file, "时间:  %s\n纬度:  %s%s\n经度:  %s%s\r\n温度:  %f\r\n", fullTime, g_gps_split_data[2], g_gps_split_data[3], g_gps_split_data[4], g_gps_split_data[5], g_water_temp);
    upFileNum(PUMP_CONFIG_FILE_PATH, g_pumpFileList.FileNum);
    pthread_mutex_unlock(&gps_data_mutex);
    memset(g_pumpFileList.FileName[g_pumpFileList.FileNum], 0, sizeof(g_pumpFileList.FileName[g_pumpFileList.FileNum]));
    strcpy(g_pumpFileList.FileName[g_pumpFileList.FileNum], fileName);

    fclose(file);
}

/*******************************************************************
** 函数名:     get_water_temp_cb
** 函数描述:   获取水温的回调函数
********************************************************************/
void get_water_temp_cb(short water_temp)
{
    // water_temp = 275;
    printf("temp->%d\n", water_temp);
    float temp = water_temp;
    //g_water_temp = temp / 10;
    printf("g_water_temp->%f\n", g_water_temp);
}

/*******************************************************************
** 函数名:     get_water_RecvDOS_cb
** 函数描述:   获取溶解氧的回调函数
********************************************************************/
void get_water_RecvDOS_cb(float odsValue, float tempValue, int datalen, int type)
{
    g_DOS_temp = odsValue;
    g_water_temp = tempValue;
    printf("溶解氧==%.2f 温度==%.2f\n", odsValue, tempValue);
}

    /*******************************************************************
** 函数名:     get_water_PH_cb
** 函数描述:   获取溶解氧的回调函数
********************************************************************/
    void get_water_PH_cb(float RecvBuff)
    {
        g_PH_temp = RecvBuff;
        printf("PH==%.2f\n", RecvBuff);
}

/*******************************************************************
** 函数名:     getSensorsDataCallBack
** 函数描述:   回调函数
** 参数:      sendSensorsDataToUart1 发送数据的回调函数
********************************************************************/
void getSensorsDataCallBack(void (*sendSensorsDataToUart)(char *, int, char))
{
    pthread_t serial_thread_id = 0;
    pthread_t update_thread_id = 0;
    pthread_t pwm_thread_id = 0;
    #define DOS  //关闭RTK和测深检测
    #ifndef DOS
    setRecvDataMinLength(100);
    if ((pthread_create(&serial_thread_id, NULL, usbCheckReadThread, NULL)) == -1)
    {
        printf("create recvive data thread error!\n");
    }
    #endif
    if ((pthread_create(&update_thread_id, NULL, updateSensorsDataCallBack, sendSensorsDataToUart)) == -1)
    {
        printf("create update send data thread error!\n");
    }

    if ((pthread_create(&pwm_thread_id, NULL, pwmInit, NULL)) == -1)
    {
        printf("create pwm monitor thread error!\n");
    }
    wiringPiSetup(); //初始化wiringPi设置
    //water_temp_init(get_water_temp_cb); //水温使用溶解氧传感器上的
    DOS_init(get_water_RecvDOS_cb, 1000000, "/dev/ttyUSB0", 9600); //1000000为数据回调频率
    PH_init(get_water_PH_cb);
}
